import type { ChildProcess } from 'node:child_process'
import { fork } from 'node:child_process'
import { EventEmitter } from 'node:events'
import { join } from 'node:path'
import { getLogger } from '../../logger/index'

// 惰性获取 logger，避免在模块加载时初始化
function getLoggerSafe() {
  try {
    return getLogger()
  }
  catch {
    // 如果 logger 未初始化，返回一个简单的 console logger
    return {
      debug: console.log.bind(console),
      info: console.log.bind(console),
      warn: console.warn.bind(console),
      error: console.error.bind(console),
    }
  }
}

/**
 * Worker 信息接口
 */
interface WorkerInfo {
  process: ChildProcess
  pid: number
  status: 'idle' | 'busy' | 'dead'
  currentTaskId: string | null
  lastHeartbeat: number
  tasksCompleted: number
  tasksFailed: number
}

/**
 * 进程池管理器
 *
 * 职责：管理 Worker 进程生命周期
 * 功能：
 * - Worker 进程启动/停止
 * - Worker 健康检查
 * - 进程崩溃自动重启
 * - 负载均衡（任务分发）
 * - 资源监控（内存、CPU）
 */
export class WorkerPoolManager extends EventEmitter {
  private workers: Map<number, WorkerInfo> = new Map()
  private maxWorkers: number
  private minWorkers: number
  private workerScript: string
  private healthCheckInterval?: NodeJS.Timeout

  constructor(maxWorkers: number = 50, minWorkers: number = 3) {
    super()
    this.maxWorkers = maxWorkers
    this.minWorkers = minWorkers
    // Worker 脚本路径
    // electron-vite 会将 TypeScript 编译到 out/main/ 目录
    // 开发和生产环境都使用编译后的 JavaScript 文件
    const isDev = process.env.NODE_ENV !== 'production' || !process.resourcesPath
    if (isDev) {
      // 开发环境：使用源文件路径（electron-vite 会自动处理）
      // 但实际运行时，文件会被编译到 out/main/booking/multiprocess/worker-process.js
      this.workerScript = join(__dirname, 'worker-process.js')
    }
    else {
      // 生产环境：使用编译后的文件
      // electron-vite 编译后的文件在 out/main/ 目录
      this.workerScript = join(__dirname, 'worker-process.js')
    }
  }

  /**
   * 初始化进程池：预热 Worker 进程
   * 50个Worker的启动时间约2-3秒，总内存约780MB
   */
  async initialize(): Promise<void> {
    getLoggerSafe().info('开始初始化 Worker 进程池', {
      maxWorkers: this.maxWorkers,
      minWorkers: this.minWorkers,
    })

    // 并发启动所有Worker（加快启动速度）
    const spawnPromises: Promise<WorkerInfo>[] = []
    for (let i = 0; i < this.maxWorkers; i++) {
      spawnPromises.push(this.spawnWorker())
    }

    // 等待所有Worker启动完成
    await Promise.all(spawnPromises)

    // 启动健康检查
    this.startHealthCheck()

    getLoggerSafe().info('Worker 进程池初始化完成', {
      workerCount: this.workers.size,
      estimatedMemoryMB: this.workers.size * 15 + 30,
    })

    this.emit('initialized', {
      workerCount: this.workers.size,
      estimatedMemoryMB: this.workers.size * 15 + 30,
    })
  }

  /**
   * 启动单个 Worker 进程
   */
  private async spawnWorker(): Promise<WorkerInfo> {
    const workerProcess = fork(this.workerScript, [], {
      stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
      cwd: process.cwd(),
      env: { ...process.env, WORKER_MODE: 'true' },
    })

    const workerInfo: WorkerInfo = {
      process: workerProcess,
      pid: workerProcess.pid!,
      status: 'idle',
      currentTaskId: null,
      lastHeartbeat: Date.now(),
      tasksCompleted: 0,
      tasksFailed: 0,
    }

    // 捕获 Worker 的 stdout 和 stderr 输出（用于调试）
    if (workerProcess.stdout) {
      workerProcess.stdout.on('data', (data) => {
        console.log(`[Worker ${workerInfo.pid} stdout]:`, data.toString())
      })
    }
    if (workerProcess.stderr) {
      workerProcess.stderr.on('data', (data) => {
        console.error(`[Worker ${workerInfo.pid} stderr]:`, data.toString())
      })
    }

    // 监听 Worker 消息
    workerProcess.on('message', (message: any) => {
      this.handleWorkerMessage(workerInfo, message)
    })

    // 监听 Worker 退出
    workerProcess.on('exit', (code, signal) => {
      this.handleWorkerExit(workerInfo, code, signal)
    })

    // 监听 Worker 错误
    workerProcess.on('error', (error) => {
      this.handleWorkerError(workerInfo, error)
    })

    // 等待 Worker 就绪信号
    await new Promise<void>((resolve, reject) => {
      const timeout = setTimeout(() => {
        reject(new Error(`Worker ${workerInfo.pid} 启动超时`))
      }, 10000) // 10秒超时

      workerProcess.once('message', (message: any) => {
        if (message.type === 'ready') {
          clearTimeout(timeout)
          resolve()
        }
      })
    })

    this.workers.set(workerInfo.pid, workerInfo)
    getLoggerSafe().debug('Worker 进程启动成功', { pid: workerInfo.pid })
    this.emit('worker:spawned', workerInfo.pid)

    return workerInfo
  }

  /**
   * 处理 Worker 消息
   */
  private handleWorkerMessage(worker: WorkerInfo, message: any): void {
    worker.lastHeartbeat = Date.now()

    switch (message.type) {
      case 'ready':
        worker.status = 'idle'
        break
      case 'progress':
        this.emit('task:progress', message.taskId, message)
        break
      case 'result':
        worker.status = 'idle'
        worker.currentTaskId = null
        if (message.success) {
          worker.tasksCompleted++
        }
        else {
          worker.tasksFailed++
        }
        this.emit('task:result', message.taskId, message)
        break
      case 'error':
        worker.status = 'idle'
        worker.currentTaskId = null
        worker.tasksFailed++
        this.emit('task:error', message.taskId, message)
        break
      case 'pong':
        // 心跳响应
        break
      default:
        getLoggerSafe().warn('未知的 Worker 消息类型', { type: message.type, pid: worker.pid })
    }
  }

  /**
   * 处理 Worker 退出
   */
  private handleWorkerExit(worker: WorkerInfo, code: number | null, signal: string | null): void {
    getLoggerSafe().warn('Worker 进程退出', { pid: worker.pid, code, signal })
    this.workers.delete(worker.pid)
    this.emit('worker:exited', worker.pid, code, signal)

    // 如果有未完成的任务，需要重新分配
    if (worker.status === 'busy' && worker.currentTaskId) {
      getLoggerSafe().warn('Worker 退出时仍有未完成任务', {
        pid: worker.pid,
        taskId: worker.currentTaskId,
      })
      this.emit('task:lost', worker.currentTaskId)
    }

    // 自动重启 Worker（如果当前 Worker 数量小于 minWorkers）
    if (this.workers.size < this.minWorkers) {
      getLoggerSafe().info('Worker 数量不足，准备重启', {
        current: this.workers.size,
        min: this.minWorkers,
      })
      setTimeout(() => {
        this.spawnWorker().catch((err) => {
          getLoggerSafe().error('重启 Worker 失败', { error: err })
          this.emit('error', err)
        })
      }, 1000)
    }
  }

  /**
   * 处理 Worker 错误
   */
  private handleWorkerError(worker: WorkerInfo, error: Error): void {
    getLoggerSafe().error('Worker 进程错误', { pid: worker.pid, error: error.message })
    this.emit('worker:error', worker.pid, error)
  }

  /**
   * 分配任务给 Worker
   */
  async assignTask(taskId: string, task: any): Promise<void> {
    const worker = this.getIdleWorker()
    if (!worker) {
      throw new Error('没有可用的 Worker')
    }

    worker.status = 'busy'
    worker.currentTaskId = taskId

    worker.process.send({
      type: 'task',
      taskId,
      payload: task,
    })

    getLoggerSafe().debug('任务已分配给 Worker', { taskId, workerPid: worker.pid })
  }

  /**
   * 获取空闲的 Worker（负载均衡算法：最少任务）
   */
  private getIdleWorker(): WorkerInfo | null {
    // 优先选择空闲 Worker
    for (const worker of this.workers.values()) {
      if (worker.status === 'idle') {
        return worker
      }
    }

    // 如果没有空闲，选择任务最少的（负载均衡）
    let minTasks = Infinity
    let selectedWorker: WorkerInfo | null = null

    for (const worker of this.workers.values()) {
      const totalTasks = worker.tasksCompleted + worker.tasksFailed
      if (totalTasks < minTasks) {
        minTasks = totalTasks
        selectedWorker = worker
      }
    }

    return selectedWorker
  }

  /**
   * 启动健康检查（定期检查 Worker 心跳）
   */
  private startHealthCheck(): void {
    if (this.healthCheckInterval) {
      clearInterval(this.healthCheckInterval)
    }

    // 每5秒检查一次
    this.healthCheckInterval = setInterval(() => {
      const now = Date.now()
      for (const worker of this.workers.values()) {
        const timeSinceHeartbeat = now - worker.lastHeartbeat
        if (timeSinceHeartbeat > 30000) { // 30秒无响应
          getLoggerSafe().warn('Worker 心跳超时', {
            pid: worker.pid,
            timeSinceHeartbeat,
            status: worker.status,
          })
          worker.status = 'dead'
          // 准备重启
          this.restartWorker(worker)
        }
      }
    }, 5000)
  }

  /**
   * 重启 Worker
   */
  private async restartWorker(worker: WorkerInfo): Promise<void> {
    getLoggerSafe().info('准备重启 Worker', { pid: worker.pid })

    // 杀死旧进程
    try {
      worker.process.kill('SIGTERM')
      // 等待5秒，如果还没退出就强制杀死
      setTimeout(() => {
        if (!worker.process.killed) {
          worker.process.kill('SIGKILL')
        }
      }, 5000)
    }
    catch (error) {
      getLoggerSafe().error('杀死 Worker 进程失败', { pid: worker.pid, error })
    }

    // 从列表中移除
    this.workers.delete(worker.pid)

    // 启动新进程
    try {
      await this.spawnWorker()
    }
    catch (error) {
      getLoggerSafe().error('重启 Worker 失败', { error })
    }
  }

  /**
   * 关闭进程池
   */
  async shutdown(): Promise<void> {
    getLoggerSafe().info('开始关闭 Worker 进程池', { workerCount: this.workers.size })

    // 停止健康检查
    if (this.healthCheckInterval) {
      clearInterval(this.healthCheckInterval)
      this.healthCheckInterval = undefined
    }

    const shutdownPromises: Promise<void>[] = []

    for (const worker of this.workers.values()) {
      shutdownPromises.push(
        new Promise<void>((resolve) => {
          worker.process.once('exit', () => {
            getLoggerSafe().debug('Worker 进程已退出', { pid: worker.pid })
            resolve()
          })

          // 发送停止信号
          worker.process.send({ type: 'stop' })

          // 强制终止（如果5秒内未正常退出）
          setTimeout(() => {
            if (!worker.process.killed) {
              worker.process.kill('SIGKILL')
            }
            resolve()
          }, 5000)
        }),
      )
    }

    await Promise.all(shutdownPromises)
    this.workers.clear()

    getLoggerSafe().info('Worker 进程池已关闭')
  }

  /**
   * 获取 Worker 统计信息
   */
  getStats(): {
    total: number
    idle: number
    busy: number
    dead: number
  } {
    let idle = 0
    let busy = 0
    let dead = 0

    for (const worker of this.workers.values()) {
      switch (worker.status) {
        case 'idle':
          idle++
          break
        case 'busy':
          busy++
          break
        case 'dead':
          dead++
          break
      }
    }

    return {
      total: this.workers.size,
      idle,
      busy,
      dead,
    }
  }
}
